package com.investmenttechnologyservices.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.logging.Logger;

public class DateUtil {
    private static final Logger log = Logger.getLogger(DateUtil.class.getName());

    private static final long MILLIS_IN_DAY = 1000 * 3600 * 24; 
	
	static SimpleDateFormat dateTimeFormatUTC = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
	static SimpleDateFormat dateFormatUTC = new SimpleDateFormat("MM/dd/yyyy");
	static {
		dateTimeFormatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
		dateFormatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
	}
	
	public static final Date addDays(Date date, int count) {
		return new Date(date.getTime() + count * MILLIS_IN_DAY);
	}

	public static Date dateTimeNowUTC() {
		return new Date();
	}

	public static Date dateNowUTC() {
		Date date = new Date();
		long millis = date.getTime();
		return new Date(millis - millis % MILLIS_IN_DAY);
	}

	public static Date dateTomUTC() {
		Date date = new Date();
		long millis = date.getTime();
		return new Date(millis + MILLIS_IN_DAY - millis % MILLIS_IN_DAY);
	}


	public static Date createDateUTC(int y, int m, int d) {
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.set(y,m-1,d,0,0,0);
		Date date= calendar.getTime();
		return date;
	}
	
	public static Date createDateUTC(Date date) {
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.setTime(date);
		return createDateUTC(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DAY_OF_MONTH));
		
	}

	public static Date createEODUTC(int y, int m, int d) {
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.set(y,m-1,d,23,59,59);
		Date date= calendar.getTime();
		return date;
	}

	public static Date createEODUTC(Date date) {
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.setTime(date);
		return createEODUTC(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DAY_OF_MONTH));
	}

	public static Date parseDateTime(String str) {
		try {
			return dateTimeFormatUTC.parse(str);
		} catch (ParseException e) {
			log.severe("Error parsing date time : " + str);
			return null;
		}
	}

	public static Date parseDate(String str) {
		try {
			return dateFormatUTC.parse(str);
		} catch (ParseException e) {
			log.severe("Error parsing date : " + str);
			return null;
		}
	}

	public static String toDateString(Date date) {
		return dateFormatUTC.format(date);
	}

	public static String toDateTimeString(Date date) {
		return dateTimeFormatUTC.format(date);
	}
	
	
	public static Date thisYear(Date date) {
//		log.info("[thisYear(in): date="+date.toString()+"]");
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.setTime(date);
		Calendar thisYear = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		thisYear.setTime(new Date());
//		log.info("[thisYear(out): thisYear.get(Calendar.YEAR)="+thisYear.get(Calendar.YEAR)+
//				", calendar.get(Calendar.MONTH)="+calendar.get(Calendar.MONTH)+
//				", calendar.get(Calendar.DAY_OF_MONTH)="+calendar.get(Calendar.DAY_OF_MONTH)+
//				", return="+createDateUTC(thisYear.get(Calendar.YEAR),calendar.get(Calendar.MONTH)+1,
//						calendar.get(Calendar.DAY_OF_MONTH)).toString()+"]");
		return createDateUTC(thisYear.get(Calendar.YEAR),calendar.get(Calendar.MONTH)+1,
				calendar.get(Calendar.DAY_OF_MONTH));
	}
	
	
	public static Date nextWeekDay(Long dow, Date date) {
//		log.info("nextWeekDay(in): dow="+dow+", date="+date.toString());
		Boolean isWeekend = true;
		while (isWeekend) {
			if (isWeekDay(dow, date)){
				isWeekend = false;
			} else {
				date = addDays(date,1);
			}
		}
//		log.info("nextWeekDay(out): date="+date.toString());
		return date;
	}
	
	public static Boolean isWeekDay(Long dow, Date date) {
//		log.info("isWeekDay(in): dow="+dow+", date="+date.toString());
		Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		calendar.setTime(date);
		Integer dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
		Boolean result = (dow & (int)Math.pow(2.0,(double)dayOfWeek))!=0;
//		log.info("isWeekDay(out): dayOfWeek="+dayOfWeek+", result="+result.toString());
		return result;
	}

}
